package za.org.jcicada.comms.impl.katcp;

import java.io.IOException;
import java.net.URI;
import java.nio.channels.SocketChannel;

import za.org.jcicada.comms.IAcceptListener;
import za.org.jcicada.comms.IConnection;
import za.org.jcicada.comms.IKatcpSerializerStrategy;
import za.org.jcicada.comms.exceptions.CommsException;
import za.org.jcicada.comms.impl.tcp.TcpAcceptor;

/**
 * Listen for clients on a KATCP/TCP server connect and spawn katcp
 * IConnections.
 */
public class KatcpAcceptor extends TcpAcceptor {

	public static final String KATCP = "katcp";
    protected final IKatcpSerializerStrategy katcpSerializer;

    public KatcpAcceptor(IAcceptListener acceptListener, URI baseLocationURI) throws IOException {
        // FIXME: There is a small window here where clients could connect to the acceptor
        // before katcpSerializer has been set. To fix this we need to refactor the starting of the
        // thread in the base class.
    	super(acceptListener, baseLocationURI);
    	this.katcpSerializer = acceptListener.getKatcpSerializerStrategy();
    }
    
    /**
     * Create a KatcpAcceptor.
     * 
     * Implements the katcomms acceptor using a KATCP/TCP server socket.
     * 
     * @param acceptListener to notify when connections are created.
     * @param host Host to listen on.
     * @param port Port to listen on.
     * @param katcpSerializer IKatcpSerializer implementation to use.
     */
    public KatcpAcceptor(IAcceptListener acceptListener, String host, int port, IKatcpSerializerStrategy katcpSerializer) throws IOException {
        // FIXME: There is a small window here where clients could connect to the acceptor
        // before katcpSerializer has been set. To fix this we need to refactor the starting of the
        // thread in the base class.
        super(acceptListener, host, port);
        this.katcpSerializer = katcpSerializer;
    }
    
    public KatcpAcceptor(IAcceptListener acceptListener, int port, IKatcpSerializerStrategy katcpSerializer) throws IOException {
        // FIXME: There is a small window here where clients could connect to the acceptor
        // before katcpSerializer has been set. To fix this we need to refactor the starting of the
        // thread in the base class.
        super(acceptListener, port);
        this.katcpSerializer = katcpSerializer;
    }

    /**
     * Override connection creation from TcpAcceptor.
     *
     * @param channel SocketChannel to use for connection.
     */
    @Override
    protected IConnection createConnection(SocketChannel channel) throws CommsException {
        return new KatcpConnection(channel, katcpSerializer);
    }

    @Override
    public String getProtocol() {
        return KATCP;
    }

}
